package org.jeecg.modules.bim.service.impl;

import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.util.oConvertUtils;
import org.jeecg.modules.bim.entity.BimStructureInfo;
import org.jeecg.modules.bim.entity.BimStructureInfoSub;
import org.jeecg.modules.bim.mapper.BimStructureInfoMapper;
import org.jeecg.modules.bim.service.IBimStructureInfoService;
import org.jeecg.modules.bim.service.IBimStructureInfoSubService;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;

/**
 * @Description: 模型构件信息表
 * @Author: chenliang
 * @Date: 2022-09-23
 * @Version: V1.0
 */
@Service
public class BimStructureInfoServiceImpl extends ServiceImpl<BimStructureInfoMapper, BimStructureInfo> implements IBimStructureInfoService {

    @Autowired
    private IBimStructureInfoSubService infoSubService;

    @Override
    public void addBimStructureInfo(BimStructureInfo bimStructureInfo) {
        if (oConvertUtils.isEmpty(bimStructureInfo.getPid())) {
            bimStructureInfo.setPid(IBimStructureInfoService.ROOT_PID_VALUE);
        } else {
            //如果当前节点父ID不为空 则设置父节点的hasChildren 为1
            BimStructureInfo parent = baseMapper.selectById(bimStructureInfo.getPid());
            if (parent != null && !"1".equals(parent.getHasChild())) {
                parent.setHasChild("1");
                baseMapper.updateById(parent);
            }
        }
        baseMapper.insert(bimStructureInfo);
        List<BimStructureInfoSub> infoSubList = bimStructureInfo.getSub();
        for (BimStructureInfoSub infoSub : infoSubList) {
            infoSub.setBaseId(bimStructureInfo.getId());
            infoSubService.save(infoSub);
        }
    }

    @Override
    public void updateBimStructureInfo(BimStructureInfo bimStructureInfo) {
        BimStructureInfo entity = this.getById(bimStructureInfo.getId());
        if (entity == null) {
            throw new JeecgBootException("未找到对应实体");
        }
        QueryWrapper<BimStructureInfoSub> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("base_id", bimStructureInfo.getId());
        infoSubService.remove(queryWrapper);
        List<BimStructureInfoSub> infoSub = bimStructureInfo.getSub();
        for (BimStructureInfoSub structureInfoSub : infoSub) {
            structureInfoSub.setBaseId(bimStructureInfo.getId());
            if (structureInfoSub.getId() == null) {
                infoSubService.save(structureInfoSub);
            } else {
                BimStructureInfoSub sub = new BimStructureInfoSub();
                sub.setName(structureInfoSub.getName());
                sub.setBaseId(structureInfoSub.getBaseId());
                sub.setBimValue(structureInfoSub.getBimValue());
                sub.setType(structureInfoSub.getType());
                infoSubService.save(sub);
            }
        }
        String old_pid = entity.getPid();
        String new_pid = bimStructureInfo.getPid();
        if (!old_pid.equals(new_pid)) {
            updateOldParentNode(old_pid);
            if (oConvertUtils.isEmpty(new_pid)) {
                bimStructureInfo.setPid(IBimStructureInfoService.ROOT_PID_VALUE);
            }
            if (!IBimStructureInfoService.ROOT_PID_VALUE.equals(bimStructureInfo.getPid())) {
                baseMapper.updateTreeNodeStatus(bimStructureInfo.getPid(), IBimStructureInfoService.HASCHILD);
            }
        }
        baseMapper.updateById(bimStructureInfo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteBimStructureInfo(String id) throws JeecgBootException {
        //删除子表
        QueryWrapper<BimStructureInfoSub> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("base_id", id);
        infoSubService.remove(queryWrapper);
        //查询选中节点下所有子节点一并删除
        id = this.queryTreeChildIds(id);
        if (id.indexOf(",") > 0) {
            StringBuffer sb = new StringBuffer();
            String[] idArr = id.split(",");
            for (String idVal : idArr) {
                if (idVal != null) {
                    BimStructureInfo bimStructureInfo = this.getById(idVal);
                    String pidVal = bimStructureInfo.getPid();
                    //查询此节点上一级是否还有其他子节点
                    List<BimStructureInfo> dataList = baseMapper.selectList(new QueryWrapper<BimStructureInfo>().eq("pid", pidVal).notIn("id", Arrays.asList(idArr)));
                    if ((dataList == null || dataList.size() == 0) && !Arrays.asList(idArr).contains(pidVal)
                            && !sb.toString().contains(pidVal)) {
                        //如果当前节点原本有子节点 现在木有了，更新状态
                        sb.append(pidVal).append(",");
                    }
                }
            }
            //批量删除节点
            baseMapper.deleteBatchIds(Arrays.asList(idArr));
            //修改已无子节点的标识
            String[] pidArr = sb.toString().split(",");
            for (String pid : pidArr) {
                this.updateOldParentNode(pid);
            }
        } else {
            BimStructureInfo bimStructureInfo = this.getById(id);
            if (bimStructureInfo == null) {
                throw new JeecgBootException("未找到对应实体");
            }
            updateOldParentNode(bimStructureInfo.getPid());
            baseMapper.deleteById(id);
        }
    }

    @Override
    public List<BimStructureInfo> queryTreeListNoPage(QueryWrapper<BimStructureInfo> queryWrapper) {
        List<BimStructureInfo> dataList = baseMapper.selectList(queryWrapper);
        List<BimStructureInfo> mapList = new ArrayList<>();
        Set<String> set = new HashSet<>();
        for (BimStructureInfo data : dataList) {
            QueryWrapper<BimStructureInfoSub> infoSubQueryWrapper = new QueryWrapper<>();
            infoSubQueryWrapper.eq("base_id", data.getId());
            List<BimStructureInfoSub> infoSubList = infoSubService.list(infoSubQueryWrapper);
            data.setSub(infoSubList);
            String pidVal = data.getPid();
            //递归查询子节点的根节点
            if (pidVal != null && !"0".equals(pidVal)) {
                BimStructureInfo rootVal = this.getTreeRoot(pidVal);
                if (rootVal != null && set.add(rootVal.getId())) {
                    mapList.add(rootVal);
                }
            } else {
                if (set.add(data.getId())) {
                    mapList.add(data);
                }
            }
        }
        return mapList;
    }

    /**
     * 查询结构树
     *
     * @param bimStructureInfo 父节点，为null时去数据库查询
     * @return List<BimStructureInfo> 组成树结构返回
     */
    @Override
    public List<BimStructureInfo> getTreeList(BimStructureInfo bimStructureInfo) {
        if (null == bimStructureInfo || null == bimStructureInfo.getId()) {
            // 查询父节点
            QueryWrapper<BimStructureInfo> infoQueryWrapper = new QueryWrapper<>();
            infoQueryWrapper.and(wrapper -> wrapper.eq("pid", 0).or().isNull("pid"));
            infoQueryWrapper.eq("is_visible", 1);
            List<BimStructureInfo> selectList = baseMapper.selectList(infoQueryWrapper);
            if (null == selectList || selectList.size() == 0) {
                return new ArrayList<>();
            }
            for (BimStructureInfo structureInfo : selectList) {
                // 设置路径
                structureInfo.setPath("@" + structureInfo.getId() + "@");
                List<BimStructureInfo> childList = this.getChildByParentNode(structureInfo);
                structureInfo.setChild(childList);
            }
            return selectList;
        }
        return this.getChildByParentNode(bimStructureInfo);
    }

    /**
     * 根据父节点查询所有子节点-以树结构返回
     *
     * @param info 父节点
     * @return 以树结构返回当前父节点所有子节点, 不包含父节点
     */
    @Override
    public List<BimStructureInfo> getChildByParentNode(BimStructureInfo info) {
        // 查询节点直属子级
        QueryWrapper<BimStructureInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("pid", info.getId());
        queryWrapper.eq("is_visible", 1);
        List<BimStructureInfo> infoList = baseMapper.selectList(queryWrapper);
        if (null == infoList || infoList.size() == 0) {
            return null;
        }
        for (BimStructureInfo bimStructureInfo : infoList) {
            // 设置路径
            bimStructureInfo.setPath(info.getPath() + bimStructureInfo.getId() + "@");
            // 递归
            List<BimStructureInfo> childList = getChildByParentNode(bimStructureInfo);
            bimStructureInfo.setChild(childList);
        }
        return infoList;
    }

    /**
     * 根据所传pid查询旧的父级节点的子节点并修改相应状态值
     *
     * @param pid
     */
    private void updateOldParentNode(String pid) {
        if (!IBimStructureInfoService.ROOT_PID_VALUE.equals(pid)) {
            Integer count = Math.toIntExact(baseMapper.selectCount(new QueryWrapper<BimStructureInfo>().eq("pid", pid)));
            if (count == null || count <= 1) {
                baseMapper.updateTreeNodeStatus(pid, IBimStructureInfoService.NOCHILD);
            }
        }
    }

    /**
     * 递归查询节点的根节点
     *
     * @param pidVal
     * @return
     */
    private BimStructureInfo getTreeRoot(String pidVal) {
        BimStructureInfo data = baseMapper.selectById(pidVal);
        QueryWrapper<BimStructureInfoSub> infoSubQueryWrapper = new QueryWrapper<>();
        infoSubQueryWrapper.eq("base_id", data.getId());
        List<BimStructureInfoSub> infoSubList = infoSubService.list(infoSubQueryWrapper);
        data.setSub(infoSubList);
        if (data != null && !"0".equals(data.getPid())) {
            return this.getTreeRoot(data.getPid());
        } else {
            return data;
        }
    }

    /**
     * 根据id查询所有子节点id
     *
     * @param ids
     * @return
     */
    private String queryTreeChildIds(String ids) {
        //获取id数组
        String[] idArr = ids.split(",");
        StringBuffer sb = new StringBuffer();
        for (String pidVal : idArr) {
            if (pidVal != null) {
                if (!sb.toString().contains(pidVal)) {
                    if (sb.toString().length() > 0) {
                        sb.append(",");
                    }
                    sb.append(pidVal);
                    this.getTreeChildIds(pidVal, sb);
                }
            }
        }
        return sb.toString();
    }

    /**
     * 递归查询所有子节点
     *
     * @param pidVal
     * @param sb
     * @return
     */
    private StringBuffer getTreeChildIds(String pidVal, StringBuffer sb) {
        List<BimStructureInfo> dataList = baseMapper.selectList(new QueryWrapper<BimStructureInfo>().eq("pid", pidVal));
        if (dataList != null && dataList.size() > 0) {
            for (BimStructureInfo tree : dataList) {
                if (!sb.toString().contains(tree.getId())) {
                    sb.append(",").append(tree.getId());
                }
                this.getTreeChildIds(tree.getId(), sb);
            }
        }
        return sb;
    }
}
